package com.hanlin.beforejavacodesummary.controller;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.util.List;
import java.util.Map;

public class XWPFTemplateCleaner {
    
    /**
     * 编译模板、渲染数据并删除空行
     */
    public static void renderAndClean(String sourceFile, Map<String, Object> map, 
                                    String outputPath, Configure configure) throws IOException {
        // 编译和渲染模板
        XWPFTemplate template = XWPFTemplate.compile(sourceFile, configure).render(map);
        
        // 获取渲染后的文档
        XWPFDocument document = template.getXWPFDocument();
        
        // 删除空行
        removeEmptyLines(document);
        
        // 输出到文件
        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            document.write(out);
        }
        
        template.close();
    }
    
    /**
     * 删除文档中的空行
     */
    private static void removeEmptyLines(XWPFDocument document) {
        // 删除空段落
        removeEmptyParagraphs(document);
        
        // 删除空表格行
        removeEmptyTableRows(document);
        
        // 删除没有图片的列表
        removeEmptyLists(document);
    }
    
    /**
     * 删除空段落
     */
    private static void removeEmptyParagraphs(XWPFDocument document) {
        // 使用倒序删除避免位置变化问题
        for (int i = document.getParagraphs().size() - 1; i >= 0; i--) {
            XWPFParagraph paragraph = document.getParagraphs().get(i);
            if (isEmptyParagraph(paragraph)) {
                int pos = document.getPosOfParagraph(paragraph);
                if (pos != -1) {
                    document.removeBodyElement(pos);
                }
            }
        }
    }
    
    /**
     * 删除空表格行
     */
    private static void removeEmptyTableRows(XWPFDocument document) {
        for (XWPFTable table : document.getTables()) {
            for (int i = table.getRows().size() - 1; i >= 0; i--) {
                XWPFTableRow row = table.getRows().get(i);
                if (isEmptyTableRow(row)) {
                    table.removeRow(i);
                }
            }
        }
    }
    
    /**
     * 删除没有图片的列表
     */
    private static void removeEmptyLists(XWPFDocument document) {
        // 获取文档中的所有编号段落（列表）
        List<XWPFParagraph> numberedParagraphs = getNumberedParagraphs(document);
        
        // 使用倒序删除避免位置变化问题
        for (int i = numberedParagraphs.size() - 1; i >= 0; i--) {
            XWPFParagraph paragraph = numberedParagraphs.get(i);
            if (isEmptyListParagraph(paragraph)) {
                int pos = document.getPosOfParagraph(paragraph);
                if (pos != -1) {
                    document.removeBodyElement(pos);
                }
            }
        }
    }
    
    /**
     * 获取文档中的所有编号段落（列表项）
     */
    private static List<XWPFParagraph> getNumberedParagraphs(XWPFDocument document) {
        List<XWPFParagraph> numberedParagraphs = new java.util.ArrayList<>();
        
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            if (isNumberedParagraph(paragraph)) {
                numberedParagraphs.add(paragraph);
            }
        }
        
        return numberedParagraphs;
    }
    
    /**
     * 判断段落是否为编号段落（列表项）
     */
    private static boolean isNumberedParagraph(XWPFParagraph paragraph) {
        if (paragraph == null) return false;
        
        // 方法1：检查段落是否有编号ID
        if (paragraph.getNumID() != null) {
            return true;
        }
        
        // 方法2：检查段落样式是否包含列表样式
        String style = paragraph.getStyle();
        if (style != null && (style.toLowerCase().contains("list") || 
            style.toLowerCase().contains("bullet") || 
            style.toLowerCase().contains("number"))) {
            return true;
        }
        
        // 方法3：检查段落文本是否以数字、字母或符号开头（常见的列表标记）
        String text = paragraph.getText();
        if (text != null && !text.trim().isEmpty()) {
            String trimmedText = text.trim();
            // 匹配数字+点、字母+点、-、•、◦ 等列表标记
            if (trimmedText.matches("^\\d+\\..*") || 
                trimmedText.matches("^[a-zA-Z]\\..*") || 
                trimmedText.matches("^[-•◦▪].*")) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 判断列表段落是否为空（没有图片且没有有效文本）
     */
    private static boolean isEmptyListParagraph(XWPFParagraph paragraph) {
        if (paragraph == null) return true;
        
        // 检查是否有图片
        if (hasImageInParagraph(paragraph)) {
            return false; // 有图片，保留
        }
        
        // 检查是否有有效文本
        String text = paragraph.getText();
        if (text != null && !text.trim().isEmpty()) {
            // 去除列表标记后检查是否还有内容
            String contentWithoutMarkers = removeListMarkers(text.trim());
            if (!contentWithoutMarkers.isEmpty()) {
                return false; // 有文本内容，保留
            }
        }
        
        // 检查运行(run)中的文本
        for (XWPFRun run : paragraph.getRuns()) {
            String runText = run.getText(0);
            if (runText != null && !runText.trim().isEmpty()) {
                String contentWithoutMarkers = removeListMarkers(runText.trim());
                if (!contentWithoutMarkers.isEmpty()) {
                    return false; // 有文本内容，保留
                }
            }
        }
        
        return true; // 没有图片也没有有效文本，删除
    }
    
    /**
     * 去除文本中的列表标记
     */
    private static String removeListMarkers(String text) {
        if (text == null || text.isEmpty()) return "";
        
        // 移除常见的列表标记
        return text.replaceAll("^\\d+\\.\\s*", "")        // 数字+点
                  .replaceAll("^[a-zA-Z]\\.\\s*", "")     // 字母+点
                  .replaceAll("^[-•◦▪]\\s*", "")          // 各种项目符号
                  .replaceAll("^\\s+", "")                // 开头空白
                  .trim();
    }
    
    /**
     * 判断段落中是否包含图片
     */
    private static boolean hasImageInParagraph(XWPFParagraph paragraph) {
        if (paragraph == null) return false;
        
        for (XWPFRun run : paragraph.getRuns()) {
            if (hasImageInRun(run)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 判断Run中是否包含图片
     */
    private static boolean hasImageInRun(XWPFRun run) {
        if (run == null) return false;
        
        // 方法1: 检查嵌入式图片
        if (!run.getEmbeddedPictures().isEmpty()) {
            return true;
        }
        
        // 方法2: 检查CTDrawing（更可靠的方法）
        if (run.getCTR().getDrawingList().size() > 0) {
            return true;
        }
        
        // 方法3: 检查所有XML子元素
        if (run.getCTR().sizeOfDrawingArray() > 0) {
            return true;
        }
        
        return false;
    }
    
    /**
     * 判断段落是否为空
     */
    private static boolean isEmptyParagraph(XWPFParagraph paragraph) {
        if (paragraph == null) return true;
        
        // 如果是列表段落，使用专门的判断方法
        if (isNumberedParagraph(paragraph)) {
            return isEmptyListParagraph(paragraph);
        }
        
        String text = paragraph.getText();
        if (text != null && !text.trim().isEmpty()) {
            return false;
        }
        
        // 检查所有文本运行
        for (XWPFRun run : paragraph.getRuns()) {
            String runText = run.getText(0);
            if (runText != null && !runText.trim().isEmpty()) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 判断表格行是否为空
     */
    private static boolean isEmptyTableRow(XWPFTableRow row) {
        for (XWPFTableCell cell : row.getTableCells()) {
            // 检查单元格文本
            String cellText = cell.getText();
            if (cellText != null && !cellText.trim().isEmpty()) {
                return false;
            }
            
            // 检查单元格内的段落
            for (XWPFParagraph paragraph : cell.getParagraphs()) {
                if (!isEmptyParagraph(paragraph)) {
                    return false;
                }
            }
            
            // 检查单元格内是否有图片
            if (hasImageInTableCell(cell)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 判断表格单元格中是否包含图片
     */
    private static boolean hasImageInTableCell(XWPFTableCell cell) {
        for (XWPFParagraph paragraph : cell.getParagraphs()) {
            if (hasImageInParagraph(paragraph)) {
                return true;
            }
        }
        return false;
    }
}